package org.danysoft.encoding_converter.core;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import org.apache.tika.io.IOUtils;
import org.danysoft.encoding_converter.core.exceptions.TooBigInputDataException;

public class ConvertHandler {

  public static InputStream convert(InputStream is, Charset outputCharset) throws IOException, TooBigInputDataException {
    
    CopyInputStream cis = new CopyInputStream(is);
    InputStream isTemp = null, isCopy = null;
    try {
      isCopy = cis.getCopy();
      isTemp = cis.getCopy();
      Charset inputCharset = CharsetRecognizer.recognizeCharset(isTemp);
      
      long bufferCapacity = isCopy.available();
      
      if (Integer.MAX_VALUE < bufferCapacity) {
        throw new TooBigInputDataException(inputCharset);
      }
      
      ByteBuffer bb = ByteBuffer.allocate((int) bufferCapacity);
      
      bb.put(IOUtils.toByteArray(isCopy));
      bb.rewind();
      
      bb = ByteBufferConverter.convertBuffer(
        bb, 
        inputCharset, 
        outputCharset
      );
      
      byte[] byteArray = new byte[bb.limit()];    
      bb.get(byteArray, 0, byteArray.length);
      
      ByteArrayInputStream bais = new ByteArrayInputStream(
        byteArray
      );
      
      return bais;
    } finally {
      try {
        if (isCopy != null) {
          isCopy.close();
        }
      } finally {
        if (isTemp != null) {
          isTemp.close();
        }
      }
    }
  }
  
  public static InputStream convert(File f, Charset outputCharset) throws IOException, TooBigInputDataException {
    
    InputStream is = null;
    try {
      is = new FileInputStream(f);
    
      return convert(is, outputCharset);
    } finally {
      if (is != null) {
        is.close();
      }
    }
  }
  
  public static void convert(InputStream is, OutputStream os, Charset outputCharset) throws IOException, TooBigInputDataException {
    
    InputStream resultIs = null;
    try {
      resultIs = convert(is, outputCharset);
      
      IOUtils.copy(resultIs, os);
      
    } finally {
      if (resultIs != null) {
        try {
          resultIs.close();
        } catch (IOException ioe) {}
      }
    }
  }

  public static void convert(InputStream is, File outFile, Charset outputCharset) throws IOException, TooBigInputDataException {
    OutputStream os = null;
    try {
      os = new FileOutputStream(outFile);
      convert(is, os, outputCharset);
    } finally {
      if (os != null) {
        os.close();
      }
    }
  }
  
  public static void convert(File inFile, File outFile, Charset outputCharset) throws IOException, TooBigInputDataException {
    InputStream is = null;
    try {
      is = new FileInputStream(inFile);
      convert(is, outFile, outputCharset);
    } finally {
      if (is != null) {
        is.close();
      }
    }
  }
  
}
